/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright Red Hat Inc. and Hibernate Authors
 */
package org.hibernate.orm.test.mapping;

import java.util.Iterator;

import org.hibernate.HibernateException;
import org.hibernate.mapping.Table;

import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

/**
 * Column aliases utilize {@link Table#getUniqueInteger()} for naming.  The
 * unique integer used to be statically generated by the Table class, meaning
 * it was dependent on mapping order.  HHH-2448 made the alias names
 * deterministic by having Configuration determine the unique integers on its
 * second pass over the Tables tree map.  AliasTest and
 * {@link MappingReorderedAliasTest} ensure that the unique integers are the
 * same, regardless of mapping ordering.
 *
 * @author Brett Meyer
 */
@DomainModel(
		annotatedClasses = { Table1.class, Table2.class, ConfEntity.class, UserConfEntity.class, UserEntity.class }
)
@SessionFactory
public class AliasTest {

	/**
	 * Column aliases utilize {@link Table#getUniqueInteger()} for naming.  The unique integer used to be statically
	 * generated by the Table class, meaning it was dependent on mapping order.  HHH-2448 made the alias names
	 * deterministic by having Configuration determine the unique integers on its second pass over the Tables tree map.
	 * AliasTest and {@link MappingReorderedAliasTest} ensure that the unique integers are the same, regardless of
	 * mapping ordering.
	 */
	@Test
	@JiraKey(value = "HHH-2448")
	public void testAliasOrdering(SessionFactoryScope scope) {
		Iterator<Table> tables = scope.getMetadataImplementor().collectTableMappings().iterator();
		Table table1 = null;
		Table table2 = null;
		while ( tables.hasNext() ) {
			Table table = tables.next();
			if ( table.getName().equals( "Table1" ) ) {
				table1 = table;
			}
			else if ( table.getName().equals( "Table2" ) ) {
				table2 = table;
			}
		}

		assertTrue( table1.getUniqueInteger() < table2.getUniqueInteger() );
	}

	@Test
	@JiraKey(value = "HHH-8371")
	public final void testUnderscoreInColumnName(SessionFactoryScope scope) {

		scope.inTransaction(
				session -> {
					UserEntity user = new UserEntity();
					user.setName( "foo" );
					session.persist( user );
					final ConfEntity conf = new ConfEntity();
					conf.setConfKey( "counter" );
					conf.setConfValue( "3" );
					final UserConfEntity uc = new UserConfEntity();
					uc.setUser( user );
					uc.setConf( conf );
					conf.getUserConf().add( uc );
					session.persist( conf );

					session.getTransaction().commit();
					session.clear();

					session.getTransaction().begin();
					user = session.find( UserEntity.class, user.getId() );

					try {
						session.flush();
					}
					catch (HibernateException e) {
						// original issue from HHH-8371
						fail( "The explicit column name's underscore(s) were not considered during alias creation." );
					}

					assertNotNull( user );
					assertEquals( "foo", user.getName() );
				}
		);
	}
}
